package cz.muni.fi.pa165.sme.web.pages.sportActivity;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import cz.muni.fi.pa165.sme.api.SportActivityService;
import cz.muni.fi.pa165.sme.api.to.SportActivityTO;
import cz.muni.fi.pa165.sme.web.common.TrackerDataTable;
import cz.muni.fi.pa165.sme.web.converters.ConvertUtils;
import cz.muni.fi.pa165.sme.web.fo.SportActivityFO;
import cz.muni.fi.pa165.sme.web.pages.TemplatePage;
import cz.muni.fi.pa165.sme.web.panels.DeletePanel;
import cz.muni.fi.pa165.sme.web.panels.EditPanel;
import cz.muni.fi.pa165.sme.web.security.Authorizer;
import org.apache.wicket.authorization.Action;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeAction;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.springframework.core.convert.ConversionService;

/**
 * @author jirankova
 */
@AuthorizeAction(action = Action.RENDER, roles = { Roles.ADMIN, Roles.USER})
public class ActivityListPage extends TemplatePage {

	private final NumberFormat numberFormat;

	@SpringBean
	private SportActivityService sportActivityService;

	@SpringBean(name = "conversionServiceFe")
	private ConversionService conversionService;

	public ActivityListPage() {
		final WebMarkupContainer activityTable = new TrackerDataTable<SportActivityFO>("activityTable",
				getColumns(),
				new ActivityDataProvider());
		activityTable.setOutputMarkupId(true);
		add(activityTable);
		add(new Label("title", new ResourceModel("title")));
		numberFormat = NumberFormat.getNumberInstance(getLocale());
	}

	private List<IColumn<SportActivityFO>> getColumns() {
		final List<IColumn<SportActivityFO>> columns = new ArrayList<IColumn<SportActivityFO>>();

		//activity title
		columns.add(new PropertyColumn<SportActivityFO>(new ResourceModel("activityTitle") ,"title") {
			@Override
			public void populateItem(final Item<ICellPopulator<SportActivityFO>> item, final String componentId,
					final IModel<SportActivityFO> rowModel) {
				item.add(new Label(componentId, rowModel.getObject().getTitle()));
			}
		});

		//activity speed
		columns.add(new PropertyColumn<SportActivityFO>(new ResourceModel("speed"), "speed") {
			@Override
			public void populateItem(final Item<ICellPopulator<SportActivityFO>> item, final String componentId,
					final IModel<SportActivityFO> rowModel) {
				if(rowModel.getObject().getSpeed() != null) {
					item.add(new Label(componentId, numberFormat.format(rowModel.getObject().getSpeed())));
				} else {
					item.add(new Label(componentId, ""));
				}
			}
		});

		if(Authorizer.isAdminLogged()) {
			//edit column
			columns.add(new EditColumn(new ResourceModel("edit")));

			//remove column
			columns.add(new RemoveColumn(new ResourceModel("remove")));
		}

		return columns;
	}

	/**
	 * Data provider for sprot activity table
	 */
	private class ActivityDataProvider extends SortableDataProvider<SportActivityFO> {
		private List<SportActivityFO> activityFOList;
		private List<SportActivityTO> sportActivityTOList;

		public ActivityDataProvider() {
			sportActivityTOList = sportActivityService.findAllSportActivities();
			activityFOList = ConvertUtils.convertList(sportActivityTOList, conversionService, SportActivityFO.class);
			setSort("activityStart", SortOrder.ASCENDING);
		}

		@Override
		public Iterator<? extends SportActivityFO> iterator(final int first, final int count) {
			return activityFOList.subList(first, first + count).iterator();
		}

		@Override
		public int size() {
			return activityFOList.size();
		}

		@Override
		public IModel<SportActivityFO> model(final SportActivityFO object) {
			return new CompoundPropertyModel<SportActivityFO>(
					new LoadableDetachableModel<SportActivityFO>() {
						@Override
						protected SportActivityFO load() {
							return object;
						}
					});
		}
	}

	private class EditColumn extends AbstractColumn<SportActivityFO> {
		public EditColumn(final IModel<String> model) {
			super(model);
		}

		@Override
		public void populateItem(final Item<ICellPopulator<SportActivityFO>> cellItem, final String componentId,
				final IModel<SportActivityFO> rowModel) {
			cellItem.add(new EditPanel(componentId, rowModel) {
				@Override
				public void onEdit() {
					setResponsePage(new ActivityEditPage(rowModel.getObject()));
				}
			});
		}
	}


	/**
	 * Column to remove sport activity
	 */
	private class RemoveColumn extends AbstractColumn<SportActivityFO> {
		public RemoveColumn(final IModel<String> displayModel) {
			super(displayModel);
		}

		@Override
		public void populateItem(final Item<ICellPopulator<SportActivityFO>> cellItem, final String componentId,
				final IModel<SportActivityFO> rowModel) {
			cellItem.add(new DeletePanel(componentId, rowModel) {
				@Override
				public void onDelete() {
					final SportActivityFO sportActivityFO = rowModel.getObject();
					sportActivityService.deleteSportActivity(conversionService.convert(sportActivityFO, SportActivityTO.class));
					setResponsePage(ActivityListPage.class);
				}
			});
		}
	}
}
